/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Model;

import java.util.*;

/**
 *
 * @author snowangelic
 */
class Centroid extends Action {
    Cluster associatedCluster;

    Centroid(Cluster assocCluster) {
        this.associatedCluster=assocCluster;

        Iterator it=getWeightList().iterator();
        while(it.hasNext()){
            Weight currentWeight=(Weight) it.next();
            Attribute currentAttribute=currentWeight.getAttribute();

            Random generator = new Random();
            int randomIndex=generator.nextInt(getDataSet().getActionNbr());
            if(currentAttribute.getType()==AttributeType.Numerical){
                this.setValue(currentAttribute,getDataSet().getValue(randomIndex, currentAttribute));
            }
            else if(currentAttribute.getType()==AttributeType.TextualDiscreet){
                ArrayList<String> strList=new ArrayList<String>();
                strList.add((String)getDataSet().getValue(randomIndex, currentAttribute));
                this.setValue(currentAttribute,strList);
            }
        }

    }

    public void recomputePosition(DataSet dataSet) {
         Iterator it=getWeightList().iterator();
         while(it.hasNext()){
            Weight currentWeight=(Weight) it.next();
            Attribute currentAttribute=currentWeight.getAttribute();
            if(currentAttribute.getType()==AttributeType.Numerical){
                float attributeValue=0;
                int count=0;
                for(int i=0;i<dataSet.getActionNbr();i++){
                    if(dataSet.getCluster(i,getAssociatedKmeans()).equals(this.getAssociatedCluster())){
                        attributeValue=attributeValue+(Float)dataSet.getValue(i, currentAttribute);
                        count++;
                    }
                }
                attributeValue=attributeValue/count;
                this.setValue(currentAttribute,attributeValue);
            }
            else if(currentAttribute.getType()==AttributeType.Numerical){
                ArrayList<String> strList=new ArrayList<String>();
                for(int i=0;i<dataSet.getActionNbr();i++){
                    if(dataSet.getCluster(i,getAssociatedKmeans()).equals(this.getAssociatedCluster())){
                        strList.add((String)dataSet.getValue(i, currentAttribute));
                    }
                }
            }
         }
    }

    public float getDistanceFromAction(Action action ,Distance distance){
        if(distance==Distance.EUCLIDIAN){
            float count=0;
            float subCount=0;
            float attributeDistance=0;
            
            Iterator it=getWeightList().iterator();
            while(it.hasNext()){
                Weight currentWeight=(Weight) it.next();
                if(currentWeight.getAttribute().getType()==AttributeType.TextualDiscreet){
                    ArrayList<String> centroidStringList=(ArrayList<String>)this.getValue(currentWeight.getAttribute());
                    String actionString=(String)action.getValue(currentWeight.getAttribute());

                    // On compte le nombre de fois que le String de l'action se trouve Dans notre liste de String
                    int stringInListCount=0;
                    for(int i=0;i<centroidStringList.size();i++){
                        if(centroidStringList.get(i).equals(actionString)) stringInListCount++;
                    }
                    // La distance maximum est 10 et la distance minimum est 0
                    attributeDistance= 10-(10*stringInListCount/centroidStringList.size());
                }
                else if(currentWeight.getAttribute().getType()==AttributeType.Numerical){
                    attributeDistance=(((Float)this.getValue(currentWeight.getAttribute()) - (Float)action.getValue(currentWeight.getAttribute())) / currentWeight.getNormalizeParameter() );
                }
                else{ System.out.println("Distance not yet implemeted"); }
                subCount=attributeDistance*attributeDistance*currentWeight.getWeight();
                count=count+subCount;
            }
            return (float) Math.sqrt(count);

        }
        else{
            System.out.println("===> ERROR : Wrong Distance <===");
            return 0;
        }
    }

    public Cluster getAssociatedCluster(){
        return associatedCluster;
    }

    private Kmeans getAssociatedKmeans() {
        return associatedCluster.getKmeans();
    }

    private DataSet getDataSet() {
        return associatedCluster.getDataSet();
    }

    private ArrayList<Weight> getWeightList() {
        return associatedCluster.getWeightList();
    }
}
